#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <type_traits>
#include <numeric>
#include <cmath>
#include <memory>
#include <stdexcept>
#include <functional>
#include <utility>

// 检查类型是否支持流式输出
template <typename T, typename = void>
struct is_printable : std::false_type
{
};

template <typename T>
struct is_printable<T, std::void_t<decltype(std::cout << std::declval<T>())>> : std::true_type
{
};

template <typename T>
inline constexpr bool is_printable_v = is_printable<T>::value;

// 检查类型是否可比较
template <typename T, typename = void>
struct is_comparable : std::false_type
{
};

template <typename T>
struct is_comparable<T, std::void_t<decltype(std::declval<T>() < std::declval<T>())>> : std::true_type
{
};

template <typename T>
inline constexpr bool is_comparable_v = is_comparable<T>::value;

// 主数据容器-支持任意类型
template <typename T,
          typename Allocator = std::allocator<T>,
          typename = void>
class DataContainer
{
private:
    std::vector<T, Allocator> data;
    std::string name;

public:
    DataContainer() : name("Unanamed Container") {}
    explicit DataContainer(const std::string &n) : name(n) {}

    DataContainer(std::initializer_list<T> il, const std::string &containerName = "Unamed Container") : name(containerName), data(il) {}

    // 容器操作 add
    void add(const T &value)
    {
        data.push_back(value);
    }

    template <typename... Args>
    void emplace(Args &&...args)
    {
        data.emplace_back(std::forward<Args>(args)...);
    }

    // 容器操作 remove
    void remove(size_t index)
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        data.erase(data.begin() + index);
    }

    // 访问元素
    T &at(size_t index)
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        return data[index];
    }

    // 迭代器支持
    auto begin()
    {
        return data.begin();
    }

    auto end()
    {
        return data.end();
    }

    auto begin() const { return data.begin(); }
    auto end() const { return data.end(); }

    // 信息查询
    size_t size() const { return data.size(); }
    bool empty() const { return data.empty(); }
    const std::string &getName() const { return name; }
    void setName(const std::string &newName) { name = newName; }

    // 通用操作，仅当类型支持比较时提供
    template <typename U = T,
              typename = std::enable_if_t<is_comparable_v<T>>>
    void sort()
    {
        std::sort(data.begin(), data.end());
    }

    // 找到最小值
    template <typename U = T,
              typename = std::enable_if_t<is_comparable_v<T>>>
    U findMin() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        return *std::min_element(data.begin(), data.end());
    }

    // 找到最大值
    template <typename U = T,
              typename = std::enable_if_t<is_comparable_v<T>>>
    U findMax() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        return *std::max_element(data.begin(), data.end());
    }

    // 打印内容，仅当类型支持流式输出时提供
    template <typename U = T,
              typename = std::enable_if_t<is_printable_v<T>>>
    void print(std::ostream &os = std::cout) const
    {
        os << "Container: " << name << "\n";
        if (empty())
        {
            os << "Empty\n";
        }
        else
        {
            for (const auto &item : data)
            {
                os << item << " ";
            }
        }
        os << "\n"
           << std::endl;
    }

    // 替换和过滤
    template <typename Func>
    auto transform(Func func) const
    {

        using ResultType = std::decay_t<decltype(func(std::declval<T>()))>;
        DataContainer<ResultType> result(name + " Transformed");
        std::transform(data.begin(), data.end(), std::back_inserter(result.data), func);
        return result;
    }

    template <typename Predicate>
    auto filter(Predicate pred) const
    {
        DataContainer<T> result(name + " Filtered");
        std::copy_if(data.begin(), data.end(), std::back_inserter(result.data), pred);
        return result;
    }
};

// 数值类型的容器特化
template <typename T, typename Allocator>
class DataContainer<T, Allocator, std::enable_if_t<std::is_arithmetic_v<T>>>
{
private:
    std::vector<T, Allocator> data;
    std::string name;

public:
    DataContainer() : name("Unanamed Container") {}
    explicit DataContainer(const std::string &n) : name(n) {}
    DataContainer(std::initializer_list<T> il, const std::string &containerName = "Unamed Container") : name(containerName), data(il) {}

    // 容器操作 add
    void add(const T &value)
    {
        data.push_back(value);
    }

    template <typename... Args>
    void emplace(Args &&...args)
    {
        data.emplace_back(std::forward<Args>(args)...);
    }

    // 容器操作 remove
    void remove(size_t index)
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        data.erase(data.begin() + index);
    }

    // 访问元素
    T &at(size_t index)
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        return data[index];
    }
    const T &at(size_t index) const
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        return data[index];
    }

    // 迭代器支持
    auto begin() { return data.begin(); }
    auto end() { return data.end(); }

    auto begin() const { return data.begin(); }
    auto end() const { return data.end(); }

    // 信息查询
    size_t size() const { return data.size(); }
    bool empty() const { return data.empty(); }
    const std::string &getName() const { return name; }
    void setName(const std::string &newName) { name = newName; }

    // 通用操作
    void sort()
    {
        std::sort(data.begin(), data.end());
    }

    // 找到最小值
    T findMin() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        return *std::min_element(data.begin(), data.end());
    }

    // 找到最大值
    T findMax() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        return *std::max_element(data.begin(), data.end());
    }

    // 打印内容
    void print(std::ostream &os = std::cout) const
    {
        os << "Container: " << name << "\n";
        if (empty())
        {
            os << "Empty\n";
        }
        else
        {
            for (const auto &item : data)
            {
                os << item << " ";
            }
        }
        os << "\n"
           << std::endl;
    }

    // 数值特有操作
    T sum() const
    {
        T result = static_cast<T>(0);
        for (const auto &item : data)
        {
            result += item;
        }
        return result;
    }

    double average() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        return static_cast<double>(sum()) / data.size();
    }

    T product() const
    {
        T result = static_cast<T>(1);
        for (const auto &item : data)
        {
            result *= item;
        }
        return result;
    }

    double variance() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        double avg = average();
        double sum_squared_diff = 0.0;
        for (const auto &item : data)
        {
            double diff = static_cast<double>(item) - avg;
            sum_squared_diff += diff * diff;
        }
        return sum_squared_diff / data.size();
    }

    // 转换为不同的数值类型
    template <typename U, typename = std::enable_if_t<std::is_arithmetic_v<U>>>
    DataContainer<U> convertTo() const
    {
        DataContainer<U> result(name + " Converted");
        for (const auto &item : data)
        {
            result.add(static_cast<U>(item));
        }
        return result;
    }

    // 数学运算
    DataContainer &applyFunction(const std::function<T(T)> &func)
    {
        for (auto &item : data)
        {
            item = func(item);
        }
        return *this;
    }

    // 操作重复，添加2个容器
    DataContainer operator+(const DataContainer &other) const
    {
        DataContainer result(*this);
        for (const auto &item : other.data)
        {
            result.add(item);
        }
        return result;
    }
};

// 字符串特化版本
template <typename Allocator>
class DataContainer<std::string, Allocator, void>
{
private:
    std::vector<std::string, Allocator> data;
    std::string name;

public:
    DataContainer() : name("Unanamed Container") {}
    explicit DataContainer(const std::string &n) : name(n) {}
    DataContainer(std::initializer_list<std::string> il, const std::string &containerName = "Unamed Container") : name(containerName), data(il) {}

    // 容器操作 add
    void add(const std::string &value) { data.push_back(value); }
    void add(std::string &&value) { data.push_back(std::move(value)); }

    template <typename... Args>
    void emplace(Args &&...args) { data.emplace_back(std::forward<Args>(args)...); }

    // 容器操作 remove
    void remove(size_t index)
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        data.erase(data.begin() + index);
    }

    // 访问元素
    std::string &at(size_t index)
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        return data[index];
    }
    const std::string &at(size_t index) const
    {
        if (index >= data.size())
        {
            throw std::out_of_range("Index out of range");
        }
        return data[index];
    }

    // 迭代器支持
    auto begin() { return data.begin(); }
    auto end() { return data.end(); }

    auto begin() const { return data.begin(); }
    auto end() const { return data.end(); }

    // 信息查询
    size_t size() const { return data.size(); }
    bool empty() const { return data.empty(); }
    const std::string &getName() const { return name; }
    void setName(const std::string &newName) { name = newName; }

    // 通用操作
    void sort() { std::sort(data.begin(), data.end()); }

    std::string findMin() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        return *std::min_element(data.begin(), data.end());
    }

    std::string findMax() const
    {
        if (data.empty())
        {
            throw std::runtime_error("Container is empty");
        }
        return *std::max_element(data.begin(), data.end());
    }

    // 打印内容
    void print(std::ostream &os = std::cout) const
    {
        os << "Container: " << name << "\n";
        if (empty())
        {
            os << "Empty\n";
        }
        else
        {
            for (const auto &item : data)
            {
                os << item << " ";
            }
        }
        os << "\n"
           << std::endl;
    }

    // 字符串特有操作
    // 转换为大写
    DataContainer<std::string> toUpperCase() const
    {
        DataContainer<std::string> result(name + " Upper Case");
        for (const auto &item : data)
        {
            std::string upperCaseItem = item;
            std::transform(upperCaseItem.begin(), upperCaseItem.end(), upperCaseItem.begin(), [](unsigned char c)
                           { return std::toupper(c); });
            result.add(upperCaseItem);
        }
        return result;
    }

    // 转换为小写
    DataContainer<std::string> toLowerCase() const
    {
        DataContainer<std::string> result(name + " Lower Case");
        for (const auto &item : data)
        {
            std::string lowerCaseItem = item;
            std::transform(lowerCaseItem.begin(), lowerCaseItem.end(), lowerCaseItem.begin(), [](unsigned char c)
                           { return std::tolower(c); });
            result.add(lowerCaseItem);
        }
        return result;
    }

    // 包含
    bool contains(const std::string &substring) const
    {
        return std::any_of(data.begin(), data.end(), [&substring](const std::string &item)
                           { return item.find(substring) != std::string::npos; });
    }

    // 过滤
    DataContainer<std::string> filter(const std::string &substring) const
    {
        DataContainer<std::string> result(name + " Filtered");
        std::copy_if(data.begin(), data.end(), std::back_inserter(result.data), [&substring](const std::string &item)
                     { return item.find(substring) != std::string::npos; });
        return result;
    }

    // 连接
    std::string join(const std::string &delimiter = ",") const
    {
        std::string result;
        for (const auto &item : data)
        {
            if (!result.empty())
            {
                result += delimiter;
            }
            result += item;
        }
        return result;
    }
};

// 通用打印函数
template <typename Container>
void printContainer(const Container &container,const std::string &description = "")
{
    if (!description.empty())
    {
        std::cout << description << std::endl;
    }
    container.print();
}

// 工厂函数，根据初始化列表创建合适的容器
template <typename T>
auto makeContainer(std::initializer_list<T> il, const std::string &containerName)
{
    return DataContainer<T>(il, containerName);
}

// 变参模板
template <typename... Types>
class TupleContainer
{
private:
    std::tuple<DataContainer<Types>...> containers;

    // 辅助函数：打印单个容器
    template <size_t I = 0>
    void printImpl(std::ostream &os) const
    {
        if constexpr (I < sizeof...(Types))
        {
            std::get<I>(containers).print(os);
            printImpl<I + 1>(os);
        }
    }

public:
    TupleContainer(const std::string &baseName,
                   std::initializer_list<Types>... il)
        : containers(DataContainer<Types>(il, baseName + std::to_string(sizeof...(Types) - sizeof...(il)))...) {}

    
    
        
        
    // 打印所有容器
    void print(std::ostream &os = std::cout) const
    {
        os << "Tuple Container: " << sizeof...(Types) << std::endl;
        printImpl(os);
    }

    // 获取特定类型的容器
    template <typename T>
    DataContainer<T> &getContainer()
    {
        return std::get<DataContainer<T>>(containers);
    }

    template <typename T>
    const DataContainer<T> &getContainer() const
    {
        return std::get<DataContainer<T>>(containers);
    }
};

// 模板元编程示例
template <int N>
struct Sum
{
    static constexpr int value = Sum<N - 1>::value + N;
};

template <>
struct Sum<0>
{
    static constexpr int value = 0;
};

int main()
{
    std::cout << "===== DATA TEMLATE DEMOSTARTION =====" << std::endl;
    std::cout << std::endl;

    // 基本操作演示
    std::cout << "===== BASIC DEMO =====" << std::endl;
    std::cout << std::endl;
    DataContainer<int> intContainer({1, 3, 5, 7, 2}, "Integer Container");
    intContainer.add(10);
    intContainer.print();
    intContainer.add(15);
    intContainer.add(20);
    intContainer.print();
    intContainer.remove(2);
    std::cout << "After Removing index 2" << std::endl;
    intContainer.print();

    // 访问元素
    std::cout << "===== ACCESS ELEMENTS =====" << std::endl;
    std::cout << std::endl;
    std::cout << "Element at index 2: " << intContainer.at(2) << std::endl;
    // 排序
    std::cout << "===== SORT =====" << std::endl;
    std::cout << std::endl;
    intContainer.sort();
    std::cout << "After Sorting" << std::endl;
    intContainer.print();

    // 查找最大值，最小值
    std::cout << "===== FIND MAX AND MIN =====" << std::endl;
    std::cout << std::endl;
    std::cout << "Max Element: " << intContainer.findMax() << std::endl;
    std::cout << "Min Element: " << intContainer.findMin() << std::endl;

    // 数值容器特化演示
    std::cout << "===== NUMERIC CONTAINER DEMO =====" << std::endl;
    std::cout << std::endl;
    DataContainer<double> doubleContainer({1.1, 2.2, 3.3, 4.4, 5.5}, "Double Container");
    doubleContainer.print();

    // 使用数值特有操作
    std::cout << "===== NUMERIC OPERATIONS =====" << std::endl;
    std::cout << std::endl;
    std::cout << "Sum: " << doubleContainer.sum() << std::endl;
    std::cout << "Average: " << doubleContainer.average() << std::endl;
    std::cout << "Product: " << doubleContainer.product() << std::endl;
    std::cout << "Variance: " << doubleContainer.variance() << std::endl;

    // 转换为不同数值类型
    std::cout << "===== CONVERT TO DIFFERENT TYPE =====" << std::endl;
    std::cout << std::endl;
    DataContainer<int> intContainer2 = doubleContainer.convertTo<int>();
    intContainer2.print();

    // 应用数学函数
    std::cout << "===== APPLY MATH FUNCTION =====" << std::endl;
    std::cout << std::endl;
    intContainer2.applyFunction([](int x)
                                { return x * x; });
    std::cout << "After Applying Function" << std::endl;
    intContainer2.print();

    // 字符串容器特化演示
    std::cout << "===== STRING CONTAINER DEMO =====" << std::endl;
    std::cout << std::endl;
    DataContainer<std::string> stringContainer({"Hello", "World", "C++"}, "String Container");
    stringContainer.print();

    // 使用字符串特有操作
    std::cout << "===== STRING OPERATIONS =====" << std::endl;
    std::cout << std::endl;
    // 大写小写
    std::cout << "===== UPPER AND LOWER CASE =====" << std::endl;
    std::cout << std::endl;
    DataContainer<std::string> upperCaseContainer = stringContainer.toUpperCase();
    std::cout << "After Converting to Upper Case" << std::endl;
    upperCaseContainer.print();
    DataContainer<std::string> lowerCaseContainer = stringContainer.toLowerCase();
    std::cout << "After Converting to Lower Case" << std::endl;
    lowerCaseContainer.print();

    std::cout << "Contains 'World': " << (stringContainer.contains("World") ? "Yes" : "No") << std::endl;
    std::cout << "Filtered by 'o': ";
    DataContainer<std::string> filteredContainer = stringContainer.filter("o");
    filteredContainer.print();
    std::cout << "Joined with '-' : " << stringContainer.join("-") << std::endl;

    // 变换和过滤，计算每个数字的平方根
    std::cout << "===== TRANSFORM AND FILTER =====" << std::endl;
    std::cout << std::endl;
    DataContainer<double> transformedContainer = doubleContainer.applyFunction([](double x)
                                                                                { return std::sqrt(x); });
    std::cout << "After Applying Function" << std::endl;
    transformedContainer.print();

    // 过滤仅保留偶数
    DataContainer<int> evenNumbers = intContainer.applyFunction([](int x)
                                                                { return x % 2 == 0 ? x : 0; });
    std::cout << "After Applying Function" << std::endl;
    evenNumbers.print();

    // 工厂函数和辅助函数
    std::cout << "===== FACTORY FUNCTION AND AUXILIARY FUNCTION =====" << std::endl;
    std::cout << std::endl;
    auto charContainer3 = makeContainer({'a'}, "Int Container 3");
    printContainer(charContainer3,"Int Container 3");

    // 编译时计算
    std::cout << "===== COMPILE TIME CALCULATION =====" << std::endl;
    std::cout << std::endl;
    std::cout << "Sum of 1 to 5: " << Sum<5>::value << std::endl;

    // 变参模板展示
    std::cout << "===== VARIADIC TEMPLATE =====" << std::endl;
    std::cout << std::endl;
    TupleContainer<int, double, std::string> tupleContainer("Tuple Container", {1, 2, 3}, {1.1, 2.2, 3.3}, {"Hello", "World", "C++"});
    tupleContainer.print();

    // 获取特定类型的容器
    std::cout << "===== GET SPECIFIC TYPE CONTAINER =====" << std::endl;
    std::cout << std::endl;
    DataContainer<int> &intContainer3 = tupleContainer.getContainer<int>();
    intContainer3.print();

    std::cout << "===== DATA TEMLATE DEMO END =====" << std::endl;
    std::cout << std::endl;
    return 0;
}
